<!DOCTYPE html>
<html lang="en-us">
<head><head>
    <meta name="referrer" content="no-referrer"/>
    <meta name="google-site-verification" content="9vIieCe-Qpd78QOmBl63rGtIVbhY6sYyuxX3j8XWBA4" />
    <meta name="baidu-site-verification" content="LRrmH41lz7" />
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="google-site-verification" content="xBT4GhYoi5qRD5tr338pgPM5OWHHIDR6mNg1a3euekI" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <meta name="description" content="本文是对ClusterMesh（Cilium的多集群实现）的深入研究。">
    
    <meta name="keyword"  content="暴走的初号机, shinji3887, 暴走的初号机的网络日志, 暴走的初号机的博客, shinji3887 Blog, 博客, 个人网站, 互联网, Web, 云原生, PaaS, Istio, Kubernetes, 微服务, Microservice">
    <link rel="shortcut icon" href="/img/favicon.ico">

    <title>深入了解Cilium多集群-同步率400%</title>

    <link rel="canonical" href="/post/deep-dive-into-cilium-multi-cluster/">

    <link rel="stylesheet" href="https://lupeier.cn-sh2.ufileos.com/iDisqus.min.css"/>
	
    
    <link rel="stylesheet" href="https://lupeier.cn-sh2.ufileos.com/bootstrap.min.css">

    
    <link rel="stylesheet" href="https://lupeier.cn-sh2.ufileos.com/hux-blog.min.css">

    
    <link rel="stylesheet" href="https://lupeier.cn-sh2.ufileos.com/syntax.css">

    
    <link rel="stylesheet" href="https://lupeier.cn-sh2.ufileos.com/zanshang.css">

    
    <link href="/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    
    
    <script src="https://lupeier.cn-sh2.ufileos.com/jquery.min.js"></script>
    
    
    <script src="https://lupeier.cn-sh2.ufileos.com/bootstrap.min.js"></script>
    
    
    <script src="https://lupeier.cn-sh2.ufileos.com/hux-blog.min.js"></script>
</head>
</head>

<nav class="navbar navbar-default navbar-custom navbar-fixed-top">
    <div class="container-fluid">
        
        <div class="navbar-header page-scroll">
            <button type="button" class="navbar-toggle">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">L&#39;s Blog</a>
        </div>

        
        
        <div id="huxblog_navbar">
            <div class="navbar-collapse">
                <ul class="nav navbar-nav navbar-right">
                    <li>
                        <a href="/">Home</a>
                    </li>
                    
                    <li>
                        <a href="categories/tech">tech</a>
                    </li>
                    
                    <li>
                        <a href="categories/tips">tips</a>
                    </li>
                    
                    <li>
                        <a href="/about">About</a>
                    </li>
                    
                </ul>
            </div>
        </div>
        
    </div>
    
</nav>
<script>
    
    
    
    var $body   = document.body;
    var $toggle = document.querySelector('.navbar-toggle');
    var $navbar = document.querySelector('#huxblog_navbar');
    var $collapse = document.querySelector('.navbar-collapse');

    $toggle.addEventListener('click', handleMagic)
    function handleMagic(e){
        if ($navbar.className.indexOf('in') > 0) {
        
            $navbar.className = " ";
            
            setTimeout(function(){
                
                if($navbar.className.indexOf('in') < 0) {
                    $collapse.style.height = "0px"
                }
            },400)
        }else{
        
            $collapse.style.height = "auto"
            $navbar.className += " in";
        }
    }
</script>




<style type="text/css">
    header.intro-header{
        background-image: url('https://lupeier.cn-sh2.ufileos.com/bay-blue-boat-296242.jpg')
    }
</style>
<header class="intro-header" >
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <div class="post-heading">
                    <div class="tags">
                       
                       <a class="tag" href="/tags/service-mesh" title="Service Mesh">
                           Service Mesh
                        </a>
                        
                       <a class="tag" href="/tags/cilium" title="Cilium">
                           Cilium
                        </a>
                        
                    </div>
                    <h1>深入了解Cilium多集群</h1>
                    <h2 class="subheading"></h2>
                    <span  class="meta">Posted by L&#39; on Sunday, June 30, 2019
                        
                    </span>
					<br>
                </div>
            </div>
        </div>
    </div>
</header>




<article>
    <div class="container">
        <div class="row">

            
            <div class="
                col-lg-8 col-lg-offset-2
                col-md-10 col-md-offset-1
                post-container">

        		
                        <header>
                        <h2>TOC</h2>
                        </header>
                        <nav id="TableOfContents">
  <ul>
    <li>
      <ul>
        <li><a href="#用例">用例</a></li>
        <li><a href="#控制平面">控制平面</a></li>
        <li><a href="#pod-ip-路由">Pod IP 路由</a></li>
        <li><a href="#服务发现">服务发现</a></li>
        <li><a href="#透明加密">透明加密</a></li>
        <li><a href="#多集群的网络策略">多集群的网络策略</a></li>
        <li><a href="#与istio多集群的关系">与Istio多集群的关系</a></li>
        <li><a href="#准备开始">准备开始</a></li>
      </ul>
    </li>
  </ul>
</nav>
        		
        		<blockquote>
<p>原文链接：<a href="https://cilium.io/blog/2019/03/12/clustermesh">Deep Dive into Cilium Multi-cluster</a>
作者：cilium.io</p>
</blockquote>
<p>本文是对ClusterMesh（Cilium的多集群实现）的深入研究。简而言之，ClusterMesh 提供：</p>
<ul>
<li>通过隧道或直接路由，以本地性能对多个Kubernetes集群进行Pod IP路由，而无需任何网关或代理。</li>
<li>使用标准Kubernetes服务和coredns/kube-dns的透明服务发现。</li>
<li>跨多个集群的网络策略实施。 策略可以指定为Kubernetes NetworkPolicy资源或扩展的CiliumNetworkPolicy CRD。</li>
<li>透明加密，用于本地集群中的节点之间以及跨集群边界的所有通信。</li>
</ul>
<p><img src="https://upload-images.jianshu.io/upload_images/14871146-f7dca3e31d252eb9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
多集群功能以层为单位构建，您可以选择使用所有层，也可以仅选择和使用所需的层。</p>
<h3 id="用例">用例</h3>
<p>在深入研究实现细节之前，让我们回顾一下连接多个Kubernetes集群的一些用例。</p>
<h4 id="用例高可用性">用例：高可用性</h4>
<p><img src="https://upload-images.jianshu.io/upload_images/14871146-5d69ac8aba6c7b47.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
对于大多数人来说，高可用性是最明显的用例。 此用例包括在多个区域（regions）或可用区（availability zones）中运行Kubernetes集群，并在每个集群中运行相同服务的副本。 一旦失败，请求可以故障转移到其他集群。 此用例中涵盖的故障情形主要不是整个区域或故障域的完全不可用。 更可能的情况是一个集群中资源暂时不可用或配置错误导致无法在一个集群中运行或扩展特定服务。</p>
<h4 id="用例共享服务">用例：共享服务</h4>
<p>基于Kubernetes的平台的最初趋势是构建大型多租户Kubernetes集群。 为每个租户构建单个集群或为不同类别的服务构建集群越来越普遍，例如， 不同级别的安全敏感度。
<img src="https://upload-images.jianshu.io/upload_images/14871146-c950c8dfbc5a9b0d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
但是，某些服务（如密钥管理，日志记录，监控或DNS）通常仍在所有集群之间共享。 这避免了在每个租户集群中维护这些服务的操作开销。</p>
<p>此模型的主要动机是租户集群之间的隔离，为了维持该目标，租户集群连接到共享服务集群但未连接到其他租户集群。</p>
<h4 id="用例拆分有状态和无状态服务">用例：拆分有状态和无状态服务</h4>
<p>运行有状态或无状态服务的操作复杂性是非常不同的。 无状态服务易于扩展，迁移和升级。 完全使用无状态服务运行集群可使集群保持灵活和敏捷。 从一个云提供商迁移到另一个云提供商非常简单。</p>
<p>有状态服务可能会引入潜在的复杂依赖链。 迁移服务通常涉及存储迁移。
<img src="https://upload-images.jianshu.io/upload_images/14871146-98e2a381af81e811.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
为无状态和有状态分别运行独立的集群允许将依赖复杂性隔离到较少数量的集群，并使无状态集群依赖性保持自由。</p>
<h3 id="控制平面">控制平面</h3>
<h4 id="要求">要求</h4>
<ul>
<li>必须为所有Kubernetes工作节点分配唯一的IP地址，并且所有工作节点必须在彼此之间具有IP连接。</li>
<li>必须为所有集群分配唯一的PodCIDR区间。</li>
<li>必须将Cilium配置为使用etcd的kvstore。</li>
<li>集群之间的网络必须允许集群间通信。 防火墙的具体配置要求将取决于Cilium是否配置为以直接路由或隧道模式运行。</li>
</ul>
<h4 id="架构">架构</h4>
<p>控制平面基于etcd并尽可能保持简约：</p>
<ul>
<li>每个Kubernetes集群都维护自己的etcd集群，包含该集群的状态。 来自多个集群的状态永远不会在etcd本身中混淆。</li>
<li>每个集群通过一组etcd代理公开它自己的etcd。 在其他集群中运行的Cilium代理连接到etcd代理以监视更改并将多集群相关状态复制到自己的集群中。 使用etcd代理确保了etcd观察者的可扩展性。 访问受TLS证书保护。</li>
<li>从一个集群到另一个集群的访问始终是只读的。 这确保了故障域保持不变，即一个集群中的故障永远不会传播到其他集群中。</li>
<li>配置通过简单的Kubernetes secrets资源进行，该资源包含远程etcd代理的寻址信息以及访问etcd代理所需的集群名称和证书。</li>
</ul>
<p><img src="https://upload-images.jianshu.io/upload_images/14871146-47bf320d6635c354.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h3 id="pod-ip-路由">Pod IP 路由</h3>
<p>pod IP路由是多集群能力的基础。 它允许跨集群的pod通过其pod IP相互联系。 Cilium可以在多种模式下运行以执行pod IP路由。 所有这些模式都能够执行多集群pod IP路由。</p>
<h4 id="隧道模式">隧道模式</h4>
<p><img src="https://upload-images.jianshu.io/upload_images/14871146-1488d363a7db42ae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
隧道模式将pod中发出的所有网络数据包封装在所谓的封包头中。 封包头可以包含VXLAN或Geneve帧。 然后通过标准UDP包头传输该封装帧。 该概念类似于VPN隧道。</p>
<ul>
<li><strong>优点</strong>：pod IP在底层网络上永远不可见。 网络只能看到工作节点的IP地址。 这可以简化安装和防火墙规则。</li>
<li><strong>缺点</strong>：所需的额外网络标头将降低网络的理论最大吞吐量。 确切的成本取决于配置的MTU，与使用MTU 9000的巨型帧相比，使用1500的传统MTU时会更加明显。</li>
<li><strong>缺点</strong>：为了不消耗过多CPU，包括底层硬件在内的整个网络堆栈必须支持校验和和分段卸载，以计算校验和并在硬件中执行分段，就像对“常规”网络数据包所做的那样。如今，这种卸载功能的可用性非常常见。</li>
</ul>
<h4 id="直接路由模式">直接路由模式</h4>
<p><img src="https://upload-images.jianshu.io/upload_images/14871146-51340f50bb80261e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
在直接路由模式中，所有网络数据包都直接路由到网络。 这要求网络能够路由pod IP。 可以使用多个选项实现跨节点传播pod IP路由信息：</p>
<ul>
<li>使用<code>--auto-direct-node-routes</code>选项，这是通过kvstore的超轻量级路由传播方法，如果所有工作节点共享一个单一的2层网络，该选项将起作用。 对于所有形式的基于云提供商的虚拟网络，通常都满足此要求。</li>
<li>使用<a href="http://docs.cilium.io/en/stable/gettingstarted/kube-router/">kube-router集成</a>运行BGP路由守护进程。</li>
<li>使用任何其他路由守护进程将路由注入标准Linux路由表（bird，quagga，&hellip;）</li>
</ul>
<p>当网络不再理解pod IP时，网络数据包地址需要伪装。</p>
<ul>
<li><strong>优点</strong>：减少的网络数据包标头可以优化网络吞吐量和延迟。</li>
<li><strong>缺点</strong>：整个网络必须能够路由pod IP，这会增加操作的复杂性。</li>
</ul>
<h4 id="混合路由模式">混合路由模式</h4>
<p>混合路由模式允许在可用时使用直接路由，这通常在本地集群或同一VPC中的其他集群中，而当跨越VPC或云提供商时可以回退到隧道模式。 这可以限制操作复杂性并且允许仅在需要时支付优化成本。</p>
<h3 id="服务发现">服务发现</h3>
<p>Cilium的多集群模型的服务发现是使用标准的Kubernetes <a href="https://kubernetes.io/docs/concepts/services-networking/service/">services</a> 构建的，旨在对现有的Kubernetes应用程序部署完全透明：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
   <span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Service</span>
   <span style="color:#f92672">metadata</span>:
     <span style="color:#f92672">name</span>: <span style="color:#ae81ff">rebel-base</span>
     <span style="color:#f92672">annotations</span>:
       <span style="color:#f92672">io.cilium/global-service</span>: <span style="color:#e6db74">&#34;true&#34;</span>
   <span style="color:#f92672">spec</span>:
     <span style="color:#f92672">type</span>: <span style="color:#ae81ff">ClusterIP</span>
     <span style="color:#f92672">ports</span>:
     - <span style="color:#f92672">port</span>: <span style="color:#ae81ff">80</span>
     <span style="color:#f92672">selector</span>:
       <span style="color:#f92672">name</span>: <span style="color:#ae81ff">rebel-base</span>
</code></pre></div><ul>
<li>Cilium通过一个注释<code>io.cilium/global-service: &quot;true&quot;</code> 来监控Kubernetes服务和端点以及监听服务。 对于此类服务，具有相同名称和命名空间信息的所有服务将自动合并在一起，并形成跨集群可用的全局服务。</li>
<li>根据标准Kubernetes运行状况检查逻辑，任何到全局服务的ClusterIP的流量都将自动负载平衡到所有集群中的端点。</li>
<li>每个集群继续为每个服务维护自己的ClusterIP，这意味着Kubernetes和kube-dns / coredns不知道其他集群。 DNS服务器继续返回仅在本地集群中有效的ClusterIP，Cilium将透明地执行负载平衡。</li>
<li>对于细粒度控制存在若干附加注释，例如单向暴露或亲和策略。
<img src="https://upload-images.jianshu.io/upload_images/14871146-b027eb4bd91ead46.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></li>
</ul>
<p>从<code>frontend-1</code>到ClusterIP <code>30.1.1.1</code>的所有流量将自动负载均衡到集群1 的后端pod IP<code>[10.0.0.1,10.0.0.2]</code>以及集群2的后端pod IP<code>[20.0.0.1,20.0.0.2]</code>。 每个集群将执行本地后端实例的运行状况检查，并在容器创建，销毁或变得不健康时通知其他集群。</p>
<h3 id="透明加密">透明加密</h3>
<p><a href="https://cilium.io/blog/2019/02/12/cilium-14/">Cilium 1.4</a>中引入的透明加密与多集群兼容。确保使用公共密钥配置所有集群中的所有节点，如此节点之间的所有通信都会自动加密。
<img src="https://upload-images.jianshu.io/upload_images/14871146-be3e56c01fa1ef78.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h3 id="多集群的网络策略">多集群的网络策略</h3>
<p>简单版本是您从单个集群中熟悉的策略实施将简单地扩展并跨集群工作。 由于策略是使用pod标签指定的，因此允许<code>frontend</code>与<code>backend</code>通信的策略将应用于集群流量，就像流量跨越集群一样。</p>
<p>Cilium<strong>不会</strong>跨集群自动传播NetworkPolicy或CiliumNetworkPolicy。 用户有责任将策略导入所有集群。 这是有意为之，因为这意味着每个集群都可以决定是否允许集群接收来自远程集群的通信或者发出到远程集群的通信。</p>
<h4 id="允许特定集群的交叉路径">允许特定集群的交叉路径</h4>
<p>可以仅建立适用于特定集群中的pod的策略。 集群名称由Cilium表示为每个pod上的标签，允许匹配的集群名称可以是<code>endpointSelector</code>或者是由<code>toEndpoints</code>和<code>fromEndpoints</code>构造的<code>matchLabels</code>标签：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"><span style="color:#f92672">apiVersion</span>: <span style="color:#e6db74">&#34;cilium.io/v2&#34;</span>
<span style="color:#f92672">kind</span>: <span style="color:#ae81ff">CiliumNetworkPolicy</span>
<span style="color:#f92672">metadata</span>:
  <span style="color:#f92672">name</span>: <span style="color:#e6db74">&#34;allow-cross-cluster&#34;</span>
  <span style="color:#f92672">description</span>: <span style="color:#e6db74">&#34;Allow x-wing in cluster1 to contact rebel-base in cluster2&#34;</span>
<span style="color:#f92672">spec</span>:
  <span style="color:#f92672">endpointSelector</span>:
    <span style="color:#f92672">matchLabels</span>:
      <span style="color:#f92672">name</span>: <span style="color:#ae81ff">x-wing</span>
      <span style="color:#f92672">io.cilium.k8s.policy.cluster</span>: <span style="color:#ae81ff">cluster1</span>
  <span style="color:#f92672">egress</span>:
  - <span style="color:#f92672">toEndpoints</span>:
    - <span style="color:#f92672">matchLabels</span>:
        <span style="color:#f92672">name</span>: <span style="color:#ae81ff">rebel-base</span>
        <span style="color:#f92672">io.cilium.k8s.policy.cluster</span>: <span style="color:#ae81ff">cluster2</span>
</code></pre></div><p>上面的示例策略将允许cluster1中的<code>x-wing</code>与cluster2中的<code>rebel-base</code>对话。 除非存在将通信列入白名单的附加策略，否则x-wing将无法与本地集群中的rebel-base通信。</p>
<h3 id="与istio多集群的关系">与Istio多集群的关系</h3>
<p>这两个项目都是独立的，但可以很好地相互补充。 组合Cilium和Istio多集群的常用方法是使用Cilium的多集群Pod IP路由层来满足<a href="https://istio.io/docs/setup/kubernetes/multicluster-install/">Istio多集群指南</a>的以下要求：</p>
<blockquote>
<p><em>每个集群中的所有pod CIDR必须可以相互路由。</em></p>
</blockquote>
<p>此外，Cilium策略执行功能可用于保护与Istio控制平面之间的通信，以及通过不支持的协议（如UDP或IPV6）保护sidecar的旁路尝试，以及防止受损的sidecar代理。</p>
<p>还可以同时运行全局Istio服务和Cilium全局服务。 所有Istio托管服务都可以获得Cilium的全局服务，因为它们可以像常规服务一样通过DNS发现。</p>
<h3 id="准备开始">准备开始</h3>
<p>要开始使用，请按照手把手的<a href="http://docs.cilium.io/en/stable/gettingstarted/clustermesh/">ClusterMesh教程</a>进行操作，该教程将指导您完成将集群连接在一起的过程。 请务必加入我们的<a href="https://cilium.herokuapp.com/">Slack频道</a>，提出问题并展示您的设置。
<img src="https://upload-images.jianshu.io/upload_images/14871146-112faa9f90a9352b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>

        
                
        
              <hr>
              <ul class="pager">
                  
                  <li class="previous">
                      <a href="/post/steps-toward-the-glory-of-rest/" data-toggle="tooltip" data-placement="top" title="Richardson Maturity Model-迈向REST的顶点">&larr; Previous Post</a>
                  </li>
                  
                  
                  <li class="next">
                      <a href="/post/cloud-native-api-gateway-part-1/" data-toggle="tooltip" data-placement="top" title="构建云原生微服务网关系列-篇一：Ambassador">Next Post &rarr;</a>
                  </li>
                  
              </ul>
  
              

<div id="gitalk-container"></div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css">
<script src="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script>
<script src="/js/md5.min.js"></script>
<script>
	const gitalk = new Gitalk({
	  clientID: 'aff2580d8cc58af83367',
	  clientSecret: '747547f5f87fcc5145b847ab76a498d7e501319f',
	  repo: 'comment',
	  owner: 'shinji3887',
	  admin: ['shinji3887'],
	  id: md5(location.pathname),      
	  distractionFreeMode: false  
	})

	gitalk.render('gitalk-container')
</script>


            </div>
            
            <div class="
                col-lg-8 col-lg-offset-2
                col-md-10 col-md-offset-1
                sidebar-container">

                
                <section>
                    <hr class="hidden-sm hidden-xs">
                    <h5><a href="/tags/">FEATURED TAGS</a></h5>
                    <div class="tags">
                     
                    
                        
                            <a href="/tags/api-gateway" title="api-gateway">
                                api-gateway
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/cloud-native" title="cloud-native">
                                cloud-native
                            </a>
                        
                    
                        
                            <a href="/tags/devops" title="devops">
                                devops
                            </a>
                        
                    
                        
                            <a href="/tags/docker" title="docker">
                                docker
                            </a>
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/istio" title="istio">
                                istio
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/kubernetes" title="kubernetes">
                                kubernetes
                            </a>
                        
                    
                        
                            <a href="/tags/microservice" title="microservice">
                                microservice
                            </a>
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/restful" title="restful">
                                restful
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/servicemesh" title="servicemesh">
                                servicemesh
                            </a>
                        
                    
                        
                            <a href="/tags/spring-cloud" title="spring-cloud">
                                spring-cloud
                            </a>
                        
                    
                        
                            <a href="/tags/vue" title="vue">
                                vue
                            </a>
                        
                    
                        
                    
                        
                    
                    </div>
                </section>

                
                <hr>
                <h5>FRIENDS</h5>
                <ul class="list-inline">
                    
                        <li><a target="_blank" href="https://skyao.io/">小剑的博客</a></li>
                    
                        <li><a target="_blank" href="https://zhaohuabing.com/">huabing的博客</a></li>
                    
                        <li><a target="_blank" href="http://blog.didispace.com/">程序猿DD的博客</a></li>
                    
                </ul>
            </div>
        </div>
    </div>
</article>




<footer>
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <ul class="list-inline text-center">
                   
                   <li>
                       <a href="" rel="alternate" type="application/rss+xml" title="L&#39;s Blog" >
                           <span class="fa-stack fa-lg">
                               <i class="fa fa-circle fa-stack-2x"></i>
                               <i class="fa fa-rss fa-stack-1x fa-inverse"></i>
                           </span>
                       </a>
                   </li>
                   
                    
                    <li>
                        <a href="mailto:18016380795@163.com">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-envelope fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
		    
                    
                    
                    
                    

                    

		    
                    
                    <li>
                        <a target="_blank" href="/link%20of%20wechat%20QR%20code%20image">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-wechat fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
		    
                    
                    <li>
                        <a target="_blank" href="https://github.com/shinji3887">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-github fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
		    
                    
                    <li>
                        <a target="_blank" href="https://www.linkedin.com/in/lupeier">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-linkedin fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
		    
                </ul>
		<p class="copyright text-muted">
                    Copyright &copy; L&#39;s Blog , 2019
                    <br>
                    <br>
                    <a href="http://icp.chinaz.com/info?q=lupeier.com" target="_blank">备案号：沪ICP备19022667号-1</a>                    
                </p>
            </div>
        </div>
    </div>
</footer>



<script>
    function async(u, c) {
      var d = document, t = 'script',
          o = d.createElement(t),
          s = d.getElementsByTagName(t)[0];
      o.src = u;
      if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
      s.parentNode.insertBefore(o, s);
    }
</script>






<script>
    
    if($('#tag_cloud').length !== 0){
        async("/js/jquery.tagcloud.js",function(){
            $.fn.tagcloud.defaults = {
                
                color: {start: '#bbbbee', end: '#0085a1'},
            };
            $('#tag_cloud a').tagcloud();
        })
    }
</script>


<script>
    async("/js/fastclick.js", function(){
        var $nav = document.querySelector("nav");
        if($nav) FastClick.attach($nav);
    })
</script>


<script>
    (function(){
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https'){
       bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
      }
      else{
      bp.src = 'http://push.zhanzhang.baidu.com/push.js';
      }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>







</body>
</html>
